{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# python装饰器\n",
    "\n",
    "   1、装饰器是python语法层面支持的一种[装饰模式](装饰模式.ipynb)，你可以手工打造装饰模式，也可以使用语法糖@；\n",
    "   \n",
    "   2、函数是第一等公民“first class functions”，见[python函数式编程](python函数式编程.ipynb)，这是实现装饰模式的前提；"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 手工打造装饰模式 vs 装饰器语法糖@"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "deco1\n",
      "raw_fun\n",
      "deco1\n",
      "###############\n",
      "deco1\n",
      "raw_fun\n",
      "deco1\n"
     ]
    }
   ],
   "source": [
    "def raw_fun():\n",
    "    print 'raw_fun'\n",
    "    \n",
    "#装饰函数\n",
    "def deco1(f):\n",
    "    def warp():           #函数中嵌套定义函数\n",
    "        print 'deco1'\n",
    "        f()               #闭包，用到了外层函数的数据\n",
    "        print 'deco1'\n",
    "    return warp           #返回函数\n",
    "\n",
    "raw_fun = deco1(raw_fun)  #函数作为参数\n",
    "raw_fun()\n",
    "\n",
    "print '###############'\n",
    "\n",
    "@deco1                     #语法糖@\n",
    "def raw_fun():\n",
    "    print 'raw_fun'\n",
    "\n",
    "raw_fun()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 装饰器带参数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 装饰器组合"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 装饰器可以修饰什么？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 装饰器本身可以为函数，可以为类，也可以为类方法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 内置装饰器\n",
    "### @wraps\n",
    "### @staticmethod\n",
    "通常以装饰器的语法来使用，本质上它是一个类描述器,见[python描述器](python描述器.ipynb)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "m1\n",
      "m2\n",
      "m3\n",
      "<type 'function'>\n",
      "<type 'function'>\n",
      "<type 'function'>\n"
     ]
    }
   ],
   "source": [
    "#模拟内置staticmethod\n",
    "class Staticmethod(object):  \n",
    "    def __init__(self,method):  \n",
    "        self.staticmethod=method  \n",
    "    def __get__(self,object,type):  \n",
    "        return self.staticmethod\n",
    "    \n",
    "class A():\n",
    "    \n",
    "    def m1():\n",
    "        print 'm1'\n",
    "    m1 = staticmethod(m1)\n",
    "    \n",
    "    #等同于\n",
    "    @staticmethod\n",
    "    def m2():\n",
    "        print 'm2'\n",
    "        \n",
    "    #等同于\n",
    "    @Staticmethod\n",
    "    def m3():\n",
    "        print 'm3'\n",
    "        \n",
    "A.m1()\n",
    "A.m2()\n",
    "A.m3()\n",
    "print type(A.m1)\n",
    "print type(A.m2)\n",
    "print type(A.m3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### @classmethod"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "m1\n",
      "m2\n",
      "m3\n",
      "<type 'instancemethod'>\n",
      "<type 'instancemethod'>\n",
      "<type 'function'>\n"
     ]
    }
   ],
   "source": [
    "#模拟内置classmethod\n",
    "class Classmethod(object):  \n",
    "    def __init__(self,method):  \n",
    "        self.classmethod=method  \n",
    "    def __get__(self,cobject,type):  \n",
    "        def _deco():  \n",
    "            return self.classmethod(type)\n",
    "        return _deco\n",
    "    \n",
    "class A():\n",
    "    \n",
    "    def m1(cls):\n",
    "        print 'm1'\n",
    "    m1 = classmethod(m1)\n",
    "    \n",
    "    #等同于\n",
    "    @classmethod\n",
    "    def m2(cls):\n",
    "        print 'm2'\n",
    "        \n",
    "    #等同于\n",
    "    @Classmethod\n",
    "    def m3(cls):\n",
    "        print 'm3'\n",
    "        \n",
    "A.m1()\n",
    "A.m2()\n",
    "A.m3()\n",
    "print type(A.m1)\n",
    "print type(A.m2)\n",
    "print type(A.m3)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
